Makefile学习记录

您所在的位置:网站首页 subst 命令 Makefile学习记录

Makefile学习记录

#Makefile学习记录| 来源: 网络整理| 查看: 265

最近又把之前的makefile重新看了一遍,在日常还是用的很广泛的,因此记录一下,方便以后查阅

1、编译过程

我觉得要学习Makefile就必须仔细了解编译过程,不清楚这个编译过程就不知道makefile在说什么东西,特别是对于习惯了从win平台用ide来写代码的人来说,另外就是需要了解一点点的shell知识。

关于编译过程,我总结如下图所示

主要是下面的四个阶段构成,可以把这四个过程使用gcc展示出来,可以更深刻的认识一下

image

使用下面的代码进行测试

#include int add(int a, int b); int minus(int a, int b); int main() { int a = 30; int b = 5; int c; c = add(a, b); printf("a+b = %d\n", c); c = minus(a, b); printf("a-b = %d\n", c); return 0; } int add(int a, int b) { return a+b; } int minus(int a, int b) { return a-b; }

可以线使用预处理看一下

gcc -E main.c

image 加上 -o指定输出文件 gcc -E main.c -o main.i 可以看到就是吧stdio.h加进来的样子(实际情况一般不需要看预处理的文件!) image 查看汇编程序:gcc -S main.c -o main.s 生成汇编程序,不过实际情况也一般不需要,这里可以看到汇编还是文本,是可以直接打开的 image 下面看第三阶段,生成机器指令gcc -c main.c -o main.o 这个时候已经是二进制指令了,无法打开 image 当然我们也可以直接输出可执行文件gcc main.c -o main ,这个输出的main就直接是可执行文件了,可以尝试执行一下,结果如下所示! image

回顾一下上面的过程

image 这里需要注意这四条语句不是相互独立的,比如直接说最后一条语句,生成可执行文件,是经过了生成.i .s .o的这几个过程的,只是他的文件没有输出出来罢了!

下面将上面的程序做一点小改动,将add 和 minus函数单独放到一个源文件中去,那我们就需要同时编译多个文件

gcc main.c add.c minus.c -o main

运行结果如下,可以看到是正常的 image

2、编译静态库并使用

编译静态库的规则如下所示

编译成 .o 的文件gcc -c [.c] -o [自定义文件名] gcc -c [.c] [.c] ... 编静态库ar -r [lib自定义库名.a] [.o] [.o] ... 链接成可执行文件gcc [.c] [.a] -o [自定义输出文件名] gcc [.c] -o [自定义输出文件名] -l[库名] -L[库所在路径]

下面将上面程序依赖的两个文件加入编成静态库,如下所示 image

3、编译动态库并使用

编译静态库的规则如下所示

编译二进制.o文件 gcc -c -fpic [.c/.cpp][.c/.cpp]... 编库 gcc -shared [.o][.o]... -o [lib自定义库名.so] 链接库到可执行文件 gcc [.c/.cpp] -o [自定义可执行文件名] -l[库名] -L[库路径] -Wl,-rpath=[库路径]

但是这里要注意,如果按照跟我一样的下面方式进行操作 image

这样会直接提示找不到动态库,因为系统寻找动态库是需要指定一下路径的,不然只会在默认的路径下去找,因此需要首先

sudo vim .bashrc

在末尾加上这个路径 image

之后source一下

source .bashrc

这样之后再次运行就不会报错了 image

4、makefile实现

makefile的基本格式

targets : prerequisties [tab键]command

用中文翻译一下就是:

目标: 生成目标需要的文件或者是目标(目标套娃) [tab键]执行的命令

伪目标,伪目标的格式如下

.PHONY : clean

为什么要有伪目标这个概念,意思就是不管有没有clean这个文件,当运行make clean的时候就是运行clean的命令,不然的话,还是用上面的程序进行实验:

#include int add(int a, int b); int minus(int a, int b); int main() { int a = 30; int b = 5; int c; c = add(a, b); printf("a+b = %d\n", c); c = minus(a, b); printf("a-b = %d\n", c); return 0; } int add(int a, int b) { return a+b; } int minus(int a, int b) { return a-b; }

这里要注意:当只有一个文件的时候可以不编写makefile,直接make这个文件就是用gcc编译了 image

这样如果我们不使用伪目标,当有一个clean.c的文件或者clean的可执行文件,就回去执行clean这个文件而不是我们准备好的makefile命令

1、makefile变量 1、定义变量

直接用=的形式就可以,当然这个=有几种变化的形式,比如下面使用变量表示源文件和.o文件的位置

src := main.c obj := objs/main.o bin := main

几种 = 的介绍

:=

立即赋值运算符 用于在定义变量时立即求值 该值在定义后不再更改 即使在后面的语句中重新定义了该变量

?=

默认赋值运算符 如果该变量已经定义,则不进行任何操作 如果该变量尚未定义,则求值并分配

+=

累加 2、使用变量

使用$() 或者是 ${}的方式来实现

$(bin) : $(obj) gcc $(obj) -o $(bin) $(obj) : $(src) gcc -c $(src) -o $(obj) .PHONY : clean clean: rm -rf *.o main

执行如下所示: image

3、一些预定义变量,可以用预定义变量来提高效率

$@: 目标(target)的完整名称 $


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3